#!/usr/bin/env python3
"""
Fix duplicate method declarations and implementations in generated C++ code.

The generator creates:
1. Duplicate method declarations in headers (GetX/SetX methods declared twice)
2. Duplicate implementations in .cpp (both stub throwing exception AND real implementation)

This script removes duplicates keeping only the real implementations.
"""

import re
import sys
from pathlib import Path

def fix_header_duplicates(content):
    """Remove duplicate method declarations from header files."""
    lines = content.split('\n')
    seen_methods = {}
    result_lines = []
    skip_next = False

    for i, line in enumerate(lines):
        # Match method declarations
        match = re.match(r'\s*(virtual\s+)?([\w:<>,\s\*&]+)\s+(\w+)\s*\([^)]*\)\s*(const)?\s*;', line)
        if match:
            method_sig = match.group(0).strip()
            method_name = match.group(3)

            if method_sig in seen_methods:
                # Skip duplicate
                print(f"  Removing duplicate declaration: {method_name}")
                continue
            seen_methods[method_sig] = True

        result_lines.append(line)

    return '\n'.join(result_lines)

def fix_cpp_duplicates(content):
    """Remove duplicate stub implementations, keeping only real implementations."""
    # The pattern: stub implementations throw std::runtime_error
    # Real implementations access member variables or have actual logic

    # Split by function definitions
    # Look for duplicate function signatures

    lines = content.split('\n')

    # Find all function implementations on line 12 (they're all on one line)
    for i, line in enumerate(lines):
        if i == 11:  # Line 12 (0-indexed line 11)
            # This line contains all implementations concatenated
            # We need to split them and remove stubs

            # Strategy: Remove all "throw std::runtime_error" implementations
            # Keep only implementations that actually do something (return m_xxx or assign)

            # Split by method boundaries
            parts = []
            current = ""
            brace_count = 0

            for char in line:
                current += char
                if char == '{':
                    brace_count += 1
                elif char == '}':
                    brace_count -= 1
                    if brace_count == 0 and current.strip():
                        # End of a method
                        parts.append(current)
                        current = ""

            # Filter out stub implementations
            real_impls = []
            for part in parts:
                if 'throw std::runtime_error' in part:
                    print(f"  Removing stub: {part[:60]}...")
                else:
                    real_impls.append(part)

            lines[i] = ''.join(real_impls)

    return '\n'.join(lines)

def process_file(filepath):
    """Process a single C++ file to remove duplicates."""
    print(f"Processing: {filepath}")

    with open(filepath, 'r') as f:
        content = f.read()

    if filepath.suffix == '.hpp':
        fixed_content = fix_header_duplicates(content)
    elif filepath.suffix == '.cpp':
        fixed_content = fix_cpp_duplicates(content)
    else:
        return

    if fixed_content != content:
        with open(filepath, 'w') as f:
            f.write(fixed_content)
        print(f"  ✓ Fixed {filepath}")
    else:
        print(f"  - No changes needed for {filepath}")

def main():
    base_dir = Path("/home/linden/claude/zclaude/conversion-evaluation/04-cpp-generated")

    # Process all header and source files
    for repo in ["DotNetCSharpLinqByExample", "DelegateTransform", "RobloxAPI", "C5"]:
        repo_path = base_dir / repo
        if not repo_path.exists():
            continue

        print(f"\n=== Processing {repo} ===")

        for file in sorted(repo_path.glob("*.hpp")):
            process_file(file)

        for file in sorted(repo_path.glob("*.cpp")):
            process_file(file)

if __name__ == "__main__":
    main()
